JOANNEUMHomeForschungsbereicheNeuSite MapRESEARCH      englishsuchenHilfe

vorheriges Kapitel Inhalt Hilfe Beispiele laden nächstes Kapitel

Steuern des Programmablaufs

In diesem Kapitel lernen Sie:
  • Bedingtes Ausführen von Codeabschnitten (Entscheidungsstrukturen)
  • Mehrfaches Ausführen von Codeabschnitten (Kontrollstrukturen)
  • Kontrollstrukturen innerhalb anderer Kontrollstrukturen
  • Verlassen von Kontrollstrukturen und Prozeduren

Wir haben bis jetzt im Großen und Ganzen nur Programme kennengelernt, die wie ein Uhrwerk ablaufen-vom Start zum Ende, und das nur einmal. In diesem Kapitel wollen wir Entscheidungs- und Kontrollstrukturen kennenlernen. Sie steuern ein Programm in Abhängigkeit davon, welche Ereignisse während des Programmlaufes auftreten.

Bedingtes Ausführen von Codeabschnitten

VBA-Programme können in ihnen enthaltene Bedingungen überprüfen und je nach Ergebnis der Prüfung unterschiedliche Operationen ausführen.

If...Then ("Wenn...Dann")

Diese Struktur führt die in ihr stehenden Anweisungen nur dann aus, wenn die Prüfung ein logisches "Wahr" (englisch "True") ergibt, wie im folgenden Beispiel:

Sub WennDann_1()
If EinDatum <> Now Then EinDatum = Now
End Sub


oder

Sub WennDann_2()
If EinDatum < Now Then
    EinDatum = Now
    MsgBox "Das heutige Datum ist der " & EinDatum
End If
End Sub


Was ist der Unterschied? Bei der zweiten Version können Sie nach "If" beliebig viele Anweisungen schreiben, bei der ersten Version nur eine. Beachten Sie, daß die zweite Version am Ende mit der Anweisung "End If" abgeschlossen werden muß.

If...Then...ElseIf...Else...End If("Wenn...Dann...Sonst")

In dieser Struktur kann eine beliebige Anzahl verschiedener Bedingungen festgelegt werden. Die Bedingungen werden der Reihe nach geprüft. Trifft eine zu, werden die hinter ihr stehenden Anweisungen ausgeführt. Die folgenden Bedingungen werden nicht mehr geprüft.

Syntax

If Bedingung Then
Anweisungen...
ElseIf AndereBedingung Then
Anweisungen...
ElseIf WiederAndereBedingung Then
Anweisungen...
Else
Anweisungen...
End If

"Bedingung" ist immer ein logischer Vergleich, der den Wert "True" ergeben muß. Wird keine Bedingung erfüllt, werden die Anweisungen unterhalb von "Else" ausgeführt (wenn Sie dorthin keine Anweisungen setzen, funktioniert die Sache auch).

Beispiel

Sub WennDann_1()

If EinDatum = Now Then EinDatum = Now

End Sub


Sub WennDann_2()

If EinDatum < Now Then
    EinDatum = Now
    MsgBox "Das heutige Date ist der " & EinDatum
End If

End Sub


Hinweis Wenn "Bedingung" zwei Teilbedingungen enthält wie in

If (IsMissing(A) Or (A > 9))


werden beide Teilbedingungen geprüft, auch wenn schon die erste Teilbedingung "True" ergibt. Es müssen also immer beide Bedingungen prüfbar sein. Gibt es in unserem Beispiel die Variable "A" nicht, dann ist die Bedingung "IsMissing (A)" erfüllt; dennoch überprüft VBA auch die Bedingung "A > 9"-und unterbricht das Programm, weil es "A" nicht findet.

Ist es beim Erstellen des VBA-Programmes nicht klar, ob die Variable "A" zur Laufzeit vorhanden ist, müssen Sie also schreiben:

If IsMissing(A) Then
    Anweisungen...
ElseIf A > 9 Then
    Anweisungen...
End If


Wenn Sie mehr als ein, zwei Anweisungen angeben, ist es sinnvoller, sie legen die Anweisungen in eine eigene Prozedur:

If IsMissing(A) Then
    MeineProzedur
ElseIf A > 9 Then
    MeineProzedur
End If
Sub MeineProzedur()
    Anweisungen...
End Sub


Select Case

Im Gegensatz zu "If...Then...Else", wo Sie beliebig viele, sich auf ganz verschiedene Variable und Programmzustände beziehende Bedingungen angeben können, arbeitet "Select Case" mit nur einem einzigen "Testausdruck", dessen Wert Sie allerdings in beliebig vielen "Case"-Anweisungen untersuchen können. Sie können den Testausdruck auch einer Funktion zuweisen.

Syntax

Select Case Testausdruck
Case Ausdrucksliste1
Anweisungen...
Case Ausdrucksliste2
Anweisungen...
Case Else
Anweisungen...
End Select

Beispiel

Sub PrüfeFall_1()

Number = InputBox("Gib eine Zahl ein:") ' Variable initialisieren.
Select Case Number ' Zahl auswerten.
Case 1 To 5    ' Zahl im Bereich von 1 bis 5.
    TestZeichenF = "im Bereich von 1 To 5"
Case 6, 7, 8, 9, 10 ' Zahl im Bereich von 6 bis 10.
    TestZeichenF = "im Bereich von 6 To 10"
Case MeineFunktion(Number)
    TestZeichenF = "Funktion <<MeineFunktion>> ausgeführt"
Case Else  ' andere Werte.
    TestZeichenF = "nicht im Bereich von 1 bis 10"
End Select
MsgBox "Die Zahl liegt " & TestZeichenF

End Sub

Function MeineFunktion(x)

MsgBox "Bin in <<MeineFunktion>>"

End Function


Mehrfaches Ausführen desselben Codes mit Programmschleifen

Dies geschieht mit Hilfe von Schleifenstrukturen, von denen VBA drei kennt. Die Anweisungen zwischen dem Kopf und dem Fuß der Schleife werden solange ausgeführt, bis die "Schleifenbedingung" nicht mehr zutrifft.

Do While...Loop

Wiederholt einen Block mit Anweisungen, solange eine Bedingung "Wahr" (englisch "True") ist, oder bis die Bedingung "True" wird. Setzen Sie diese Schleife ein, wenn Sie beim Programmieren nicht wissen können, wie oft die Anweisungen in der Schleife zur Laufzeit des VBA-Programmes ausgeführt werden müssen.

Syntax 1

Do [{While | Until} Bedingung]
[Anweisungen]
[Exit Do]
[Anweisungen]
Loop

Syntax 2

Do
[Anweisungen]
[Exit Do]
[Anweisungen]
Loop [{While | Until}Bedingung]

Elemente

Bedingung ein Ausdruck, der entweder Wahr oder Falsch ist.

Anweisungen eine oder mehrere Anweisungen, die wiederholt werden, bis Bedingung Wahr wird.

Exit Do verläßt die Kontrollstuktur vom Typ Do...Loop "vorzeitig", also wenn "Bedingung" noch zutrifft. Exit Do läßt sich an beliebiger Stelle und beliebig oft in einer solchen Struktur verwenden. Diese Anweisung wird oft in Zusammenhang mit der Auswertung einer Bedingung (zum Beispiel If...Then) eingesetzt und setzt die Ausführung mit der ersten Anweisung im Anschluß an die Schleife fort. In verschachtelten Do...Loop übergibt Exit Do die Steuerung an die Schleife der nächst-niedrigeren Verschachtelungsstufe.

KOPFGESTEUERTE "DURCHLAUFE"-SCHLEIFE

Bei dieser Form der "Do"-Schleife wird "Bedingung" schon geprüft, bevor die Schleife auch nur ein einziges Mal durchlaufen worden ist. Ist "Bedingung" schon vor dem ersten Durchlauf "False", werden die Anweisungen kein einziges Mal ausgeführt; dasProgramm setzt in der Zeile nach "Loop" fort.

Beispiel

Sub DurchlaufeKopf_1()
LangeZeichenfolge = "Ich bin eine lange Zeichenfolge"
KurzeZeichenfolge = "i"
MsgBox ZeichenfolgenAnzahl(LangeZeichenfolge, _
    KurzeZeichenfolge)
End Sub

Function ZeichenfolgenAnzahl(LangeZnF, SuchZnF)
Position = 1
Do While InStr(Position, LangeZnF, SuchZnF)
    Position = InStr(Position, LangeZnF, SuchZnF) + 1
    Count = Count + 1
Loop
ZeichenfolgenAnzahl = Count
End Function


Die hier beschriebene Funktion sucht in einer Zeichenkette ("LangeZnF") nach einer zweiten Zeichenkette ("SuchZnF") und zählt, wie oft diese gefunden wurde. Wird die zweite Zeichenkette kein einziges Mal gefunden, dann ergibt die Bedingung "InStr(Position; LangeZnF; SuchZnF)" den Wert 0. Dies übersetzt VBA in "False"; die Schleife wird kein einziges Mal durchlaufen. Jede andere Zahl wird mit "True" übersetzt, die Schleife wird durchlaufen.

FUSSGESTEUERTE "DO"-SCHLEIFE

Bei dieser Form der Schleife werden die in der Schleife gegebenen Anweisungen zunächst ausgeführt, erst dann wird die am Ende der Schleife definierte Schleifenbedingung geprüft. Diese Form der "Durchlaufe"-Schleife verwenden Sie immer dann, wenn Sie sicher sind, daß die Anweisungen zumindest einmal ausgeführt werden müssen

Sub Durchlaufe_Fuß()
Do
BenutzerdatenVerarbeiten
Antwort = MsgBox("Weitere Daten verarbeiten?", vbYesNo)
Loop While Antwort = vbYes
End Sub

Sub BenutzerdatenVerarbeiten()
MsgBox "Bin in BenutzerdatenVerarbeiten"
End Sub


AUSFÜHREN, SOLANGE EINE BEDINGUNG FALSCH IST

Die beiden gerade gezeigten "Do"-Schleifen werden solange abgearbeitet, solange die Schleifenbedingung "True" ergibt. Mit Hilfe des Befehlswortes "BisWahr" können Sie aber auch "Durchlaufe"-Schleifen bilden, die solange durchlaufen werden, solange die Bedingung "Falsch" ergibt.

Sub Durchlaufe_Fuß()
Do
BenutzerdatenVerarbeiten
Antwort = MsgBox("Weitere Daten verarbeiten?", vbYesNo)
Loop Until Antwort = vbNo
End Sub

Sub BenutzerdatenVerarbeiten()
MsgBox "Bin in BenutzerdatenVerarbeiten"
End Sub


For...Next

Diese Art der Schleife sollten Sie immer dann verwenden, wenn die Zahl der Durchläufe zumindest während des Programmlaufes vor Eintritt in den Schleifencode feststeht. Sie wiederholt solange eine Reihe von Anweisungen, bis der Schleifenzähler einen bestimmten Wert erreicht.

Syntax

For Zähler = Anfang To Ende [Step Schritt]
[Anweisungen]
[Exit For]
[Anweisungen]
Next [Zähler]

Elemente

Die For...Next-Anweisung verwendet die folgenden Argumente:

Zähler Numerische Variable, die als Schleifenzähler dient. Ein Element eines Datenfelds oder eines benutzerdefinierten Typs ist an dieser Stelle nicht zulässig.

Anfang Startwert von Zähler.

Ende Endwert von Zähler.

Schritt Schrittweite, um die Zähler bei jedem Schleifendurchlauf verändert wird. Diese Angabe ist optional; wenn Sie sie weglassen, nimmt VBA als Schrittweite +1 an. Bitte beachten Sie, daß bei Schrittweiten, die Nachkommastellen enthalten, Rundungsfehler auftreten können!

Anweisungen  Eine oder mehrere Anweisungen zwischen For und Next, die mehrmals ausgeführt werden.

Negative Schrittweite

Wenn "Ende" größer ist als "Anfang", dann müssen Sie "Schritt" angeben. Die Schleife wird sonst kein einziges Mal durchlaufen!

Anmerkungen

Nachdem im ersten Schleifendurchlauf alle Anweisungen ausgeführt wurden, addiert das Programm Schritt zum Wert von Zähler hinzu und führt denselben Test durch wie zu Beginn des ersten Durchlaufs. Wenn der Endwert noch nicht überschritten (bzw. bei negativem Schritt unterschritten) wurde, führt das Programm die Schleife erneut aus, ansonsten setzt es die Ausführung mit der Anweisung fort, die auf die Next-Anweisung folgt.

Beachten Sie, daß Zähler nach dem Verlassen der Schleife nicht den Wert von Ende hat, sondern von Ende+Schritt beziehungsweise Ende-Schritt.

Schleife mit "Exit For" vorzeitig verlassen

Exit For führt zum sofortigen Verlassen der Schleife, auch wenn "Ende" noch nicht erreicht worden ist. Es läßt sich an beliebigen Stellen und beliebig oft in der Schleife verwenden. Exit For wird oft in Zusammenhang mit der Auswertung einer Bedingung (zum Beispiel If...Then) eingesetzt und weist das Programm an, die Ausführung mit der ersten Anweisung hinter Next fortzusetzen.

Mehrere Schleifen ineinander

Sie können For...Next-Schleifen verschachteln, indem Sie eine dieser Schleifen innerhalb einer anderen verwenden. Die Zähler für alle Schleifen müssen dabei jedoch durch verschiedene Variablennamen dargestellt werden, wie im folgenden Beispiel:

For I = 1 To 10
  For J = 1 To 10
    For K = 1 To 10
      . . .
    Next K
  Next J
Next I


Hinweis Das Argument Element (z.B. "Next K") in der Next-Anweisung ist nicht zwingend notwendig. Die Ausführung wird mit einem Element genauso fortgesetzt wie ohne Element. Eine Next-Anweisung vor der zugehörigen For-Anweisung führt zu einem Fehler.

For Each...Next

Eine hochinteressante Schleife, so richtig auf VBA zugeschniten. Sie arbeitet nämlich nicht mit Wahrheitswerten oder Zählern, sondern mit Objekten. Genauer gesagt, mit all jenen Objekten, die Auflistungen enthalten. Wieviele Elemente die Auflistung hat, brauchen Sie gar nicht zu wissen.

Syntax

For Each Element In Gruppe
[Anweisungen]
[Exit For]
[Anweisungen]
Next [Element]

Die Anweisung For Each...Next verwendet die folgenden Argumente:

Argument Beschreibung
Element Variable zum Durchlauf durch die Elemente einer Auflistung oder eines Datenfeldes. Bei Auflistungen sind für Element nur Variant-Variablen, allgemeine Variablen vom Typ Objekt oder spezielle Objektvariablen für die OLE-Automatisierung zulässig. Bei Datenfeldern sind für Element nur Variant-Variablen zulässig.
Gruppe Name einer Auflistung von Objekten oder eines Datenfeldes (abgesehen von Datenfeldern mit einem benutzerdefinierten Typ).
Anweisungen Eine oder mehrere Anweisungen, die für jedes Element in Gruppe ausgeführt werden.

Wichtig Wenn Sie For Each...Next mit Datenfeldern verwenden, können Sie den Wert der Datenfeldelemente, die durch die Kontrollvariable Element bestimmt werden, nur lesen. Es ist nicht möglich, den Wert zu ändern, indem Sie Element einen Wert zuweisen.

Beispiel  Angenommen, Sie wollen alle offenen Arbeitsmappen schließen, ausgenommen die eine, die Ihr Programm enthält. Alle Arbeitsmappen sind in dem Container-Objekt "Workbooks" enhalten-egal, wieviele es sind und wie sie heißen. Wir können dann schreiben:

Sub FürAlle_1()
For Each EineMappe In Workbooks
    If EineMappe.Name <> ThisWorkbook.Name Then EineMappe.Close
Next
End Sub


Zweites Beispiel: Wir wollen alle Zellen in einem mit der Maus markierten Bereich fett schreiben, deren Wert größer als 1000 ist:

Sub FürAlle_2()
For Each EineZelle In Selection
    Wenn EineZelle.Value > 1000 Then
        EineZelle.Font.Bold = True
    End If
Next
End Sub


EINSATZ IN DATENFELDERN

For Each...Next können Sie auch verwenden, um Datenfelder zu bearbeiten:

Sub FürAlle_InDatenfeldern_1()
Dim MeinDatenfeld(9) As Variant
For Zähler = 0 To 9
    MeinDatenfeld(Zähler) = Zähler
Next
For Each EinElement In MeinDatenfeld
    MsgBox "Aktuelles Element hat den Wert: " & _
        EinElement
Next
End Sub


Falls das Datenfeld mehr als eine Element-Dimension hat:

' In einem Datenfeld mit mehr als einer Dimension
' ist die "For Each"-Schleife nicht sinnvoll
Sub FürAlle_InDatenfeldern_2()
Dim MeinDatenfeld(9, 1) As Variant
For Zähler = 0 To 9
    MeinDatenfeld(Zähler, 1) = Zähler
Next
For Each EinElement In MeinDatenfeld
    MsgBox "Aktuelles Element hat den Wert: " & _
        EinElement
Next
End Sub


Wenn Sie diesen Code laufen lassen, werden Sie merken, daß die "For Each"-Schleife alle 20 Elemente des Datenfeldes durchläuft. Sie ist also in diesem Fall nicht brauchbar. Verwenden Sie stattdessen eine "For"-Schleife:

' Sie verwenden also besser eine "For"-Schleife
Sub Für_InDatenfeldern_1()
Dim MeinDatenfeld(9, 1) As Variant
For Zähler = 0 To 9
    MeinDatenfeld(Zähler, 1) = Zähler
Next
For Schleifenzähler = LBound(MeinDatenfeld) To _
    UBound(MeinDatenfeld)
    MsgBox "Aktuelles Element hat den Wert: " & _
        MeinDatenfeld(Schleifenzähler, 1)
Next
End Sub


Schleifen vorzeitig verlassen

Wenn eine Schleife ihren Dienst verrichtet hat, bevor die Schleifenbedingung erfüllt oder der Endstand eines Zählers überschritten worden ist, können Sie das Ausführen der Anweisungen in der Schleife mit Hilfe einer der "Exit"-Anweisungen beenden.

Exit Do
Exit For

brechen jeweils die in ihren Namen enthaltene Schleifenstruktur ab. Für das Verlassen von Prozeduren und Funktionen gibt es ähnliche Anweisungen:

Exit Sub
Exit Function

Beispiel

Der nachfolgende Code verwendet "Exit"-Anweisungen, um eine For...Next-Schleife, eine Do...Loop-Schleife und eine Sub-Prozedur zu verlassen.

Sub ExitAnweisungDemo()
  Do  ' Endlosschleife.
    For I = 1 To 1000  ' 1000 Durchläufe.
      TestNum = Int(Rnd * 1000) ' Zufallszahl generieren.
      Select Case TestNum  ' Zufallszahl auswerten.
        Case 7: Exit For  ' Wenn 7, For...Next beenden.
        Case 29: Exit Do  ' Wenn 29, Do...Loop beenden.
        Case 54: Exit Sub ' Wenn 54, Sub-Prozedur beenden.
      End Select
    Next I
  Loop
End Sub


Automatisches Ablaufen von Programmen

Beim Laden einer Arbeitsmappe

Wenn Sie eine Arbeitsmappe laden, dann untersucht EXCEL, ob es in dieser Mappe eine VBA-Prozedur mit dem Namen "auto_öffnen" gibt. Wird sie gefunden, dann werden die in ihr enthaltenen Anweisungen automatisch abgearbeitet. Gleichermassen werden Anweisungen einer Prozedur mit dem Namen "auto_schliessen" automatisch beim Schliessen einer Arbeitsmappe durchgeführt.

Laden Beispiele für die in diesem Abschnitt behandelten Anweisungen finden sich in der Datei "REISEN96.xls" im Modulblatt "Anfang".
Sub auto_öffnen()
  ...Anweisungen
End Sub

Sub auto_schliessen()
  ...Anweisungen
End Sub


Hinweis  Es kann pro Arbeitsmappe nur eine "auto_öffnen"- und eine "auto_schliessen"-Prozedur geben. Wird eine Arbeitsmappe durch VBA-Code geladen, werden die "auto"-Prozeduren nicht automatisch ausgeführt. Sie müssen mit Hilfe der "RunAutoMacros"-Methode aufgerufen werden:

In diesem Beispiel wird die Arbeitsmappe ANALYSE.XLS geöffnet und der "Auto-Open"-Makro ausgeführt.

Workbooks.Open "ANALYSE.XLS"
ActiveWorkbook.RunAutoMacros xlAutoOpen


In diesem Beispiel wird der Makro "Auto_Close" für die aktive Arbeitsmappe ausgeführt und die Arbeitsmappe geschlossen.

With ActiveWorkbook
  .RunAutoMacros xlAutoClose
  .Close
End With


Beim Aktivieren und Verlassen eines Tabellenblattes

EXCEL läßt es zu, daß ein VBA-Programm automatisch gestartet wird, sobald ein neues Blatt in den Vordergrund geholt wird. Die Anweisung dafür lautet:

Application.OnSheetActivate = ActiveWorkbook.Name & _
  "!Modul1.Meine_Aktivieren_Sub"


In diesem Beispiel wird der OnSheetActivate-Eigenschaft der Makro "Meine_Aktivieren_Sub" in Modul1 der aktiven Arbeitsmappe zugeordnet. Dieser Makro wird jedesmal ausgeführt, wenn der Benutzer ein Tabellenblatt in einer beliebigen Arbeitsmappe aktiviert.

In diesem Beispiel wird der OnSheetActivate-Makro entfernt.

Application.OnSheetActivate = ""


So allgemein wird die "OnSheetActivate"-Eigenschaft wohl kaum nützlich sein. Sie finden in der Datei "REISEN96.xls" ein lebensnäheres. Dort geht es darum, daß in einem Arbeitsblatt Nullen angezeigt werden müssen, in einem zweiten aber nicht angezeigt werden dürfen. Jedesmal, wenn zu einem anderen Blatt gewechselt wird, läuft der "OnSheetActivate"-Makro automatisch ab-er prüft dabei, ob es sich um eines der beiden Blätter aus "REISEN96.xls" handelt. Falls nicht, stellt er seine Arbeit gleich wieder ein.

'Sub Nullenanzeige()

' In der Tabelle "Reisedaten" muß die Uhrzeit "00:00" angezeigt werden
' können. Diese Uhrzeit entspricht dem Datum 1.1.1900, 00 Uhr, und
' wird durch die Zahl "0" repräsentiert.
' In diesem Blatt müssen daher Nullen angezeigt werden.

' In der Tabelle "SummenTabelle" stören dagegen die Nullen.
' Daher wird bei der Anzeige dieser Tabelle die Nullen-Anzeige ausgeschaltet.
Sub Nullenanzeige()

  ' OnSheetActivate ist global (für jede geöffnete Mappe) wirksam.
  ' Daher müssen wir prüfen, ob diese Arbeitsmappe aktiv ist.
  If ActiveWorkbook.Name <> ThisWorkbook.Name Then Exit Sub

  If ActiveSheet.Name = "Reisedaten" Then
    ActiveWindow.DisplayZeros = True
    Call AlleBeschriebenenSpaltenZeigen
  ElseIf ActiveSheet.Name = "SummenTabelle" Then
    ActiveWindow.DisplayZeros = False
    Call AlleBeschriebenenSpaltenZeigen
  End If

End Sub


Soll ein VBA-Programm beim Verlassen eines Blattes ausgeführt werden, so müssen Sie der "OnSheetDeactivate"-Eigenschaft den Namen einer VBA-Prozedur angeben, die dann jedesmal, wenn Sie von einem Blatt in ein anderes wechseln, ausgeführt wird.

vorheriges Kapitel Inhalt Hilfe Beispiele laden nächstes Kapitel

------------

Copyright © by JOANNEUM RESEARCH Forschungsgesellschaft mbH